// rgTriangle.h

#ifndef _RG_TRIANGLE_H__
#define _RG_TRIANGLE_H__

#include <graphics/rgRay.h>
#include <graphics/rgMaterial.h>

namespace rg
{
	class triangle// : public rgObject
	{
	public:
		
		triangle( const rgPoint& inA, const rgPoint& inB, const rgPoint& inC)
		{
			m_vertex[0] = inA;
			m_vertex[1] = inB;
			m_vertex[2] = inC;

			m_normal = (inC - inB) ^ (inA - inB);
			m_normal.normalizeMe();

			//m_planeDistance = m_normal * rgVector(inA);

			//calculeCenter();
		}

		void setTriangle( rgPoint inA, rgPoint inB, rgPoint inC)
		{
			m_vertex[0] = inA;
			m_vertex[1] = inB;
			m_vertex[2] = inC;

			m_normal = (inC - inB) ^ (inA - inB);
			m_normal.normalizeMe();

			//m_planeDistance = m_normal * inA;

			//calculeCenter();
		}

		inline void setMaterial( material* mat)
		{
			m_pMaterial = mat;
		}

		inline const material* const getMaterial() const
		{
			return m_pMaterial;
		}

		inline void getNormal( rgNormal& n)
		{
			n.set(m_normal.x, m_normal.y,m_normal.z);
		}

		//void calculeCenter();
		//bool tomasBen(rgRay& inRay);
/*bool rayTriTest (const rgVector& tri0, const rgVector& tri1, const rgVector& tri2, 
                 const rgVector& rayO, const rgVector& rayD, 
                 rgReal& t, rgReal& u, rgReal& v, rgReal& det)
*/
		virtual bool intersect(const rgRay& inRay, rgReal& distance)
		{
			const rgVector edge1 = m_vertex[1] - m_vertex[0];
			const rgVector edge2 = m_vertex[2] - m_vertex[0];
			const rgVector pVec = inRay.m_direction ^ edge2;
			rgReal det, t, u, v;

			det = edge1 * pVec;

			// ray is parallel to plane or comes from the back
			if (det < EPSILON) return rgFALSE;

			const rgVector tVec = inRay.m_origin - m_vertex[0];
			u = tVec * pVec;
			if (u < static_cast<rgReal> (0) || u > det) return rgFALSE;

			const rgVector qVec =  tVec ^ edge1;
			v = inRay.m_direction * qVec;
			if (v < static_cast<rgReal> (0) || u + v > det) return rgFALSE;

			t = edge2 * qVec;
			distance = t / det;
			//m_lastHit = inRay(inRay.maxL);
			
			return rgTRUE;
		}

		/*
		virtual rgVector getNormal(const rgVector& inPoint) const
		{
			return mNormal;
		}*/


		rgPoint m_vertex[3];

		//rgPoint m_position;
		rgVector m_normal;
		rgPoint m_center;

		//rgReal m_planeDistance;

		material* m_pMaterial;
		//mutable rgPoint m_lastHit;
	
	};
} // namespace rg

#endif // _RG_TRIANGLE_H__